using System;
using System.Web.Mvc;
using Headspring.Training.Core.Model;
using Headspring.Training.Core.Services;
using Headspring.Training.UI.Filters;
using Headspring.Training.UI.Models;
using MvcContrib;

namespace Headspring.Training.UI.Controllers
{
	[AuthenticationFilter]
	public class WorkOrderController : Controller
	{
		private readonly IEmployeeRepository _employeeRepository;
		private readonly IStateCommandVisitor _stateCommandVisitor;
		private readonly IUserSession _userSession;
		private readonly IWorkflowFacilitator _workflowFacilitator;
		private readonly IWorkOrderBuilder _workOrderBuilder;
		private readonly IWorkOrderRepository _workOrderRepository;

		public WorkOrderController(IEmployeeRepository employeeRepository,
		                           IWorkOrderBuilder workOrderBuilder,
		                           IUserSession userSession,
		                           IWorkflowFacilitator workflowFacilitator,
		                           IWorkOrderRepository workOrderRepository,
		                           IStateCommandVisitor stateCommandVisitor)
		{
			_employeeRepository = employeeRepository;
			_stateCommandVisitor = stateCommandVisitor;
			_workOrderRepository = workOrderRepository;
			_workflowFacilitator = workflowFacilitator;
			_userSession = userSession;
			_workOrderBuilder = workOrderBuilder;
		}

		public ActionResult New()
		{
			Employee currentUser = _userSession.GetCurrentUser();
			WorkOrder workOrder = _workOrderBuilder.CreateNewWorkOrder(currentUser);
			ViewData.Add(workOrder);

			pushEmployeeListToViewData(currentUser);
			pushValidCommandsToViewData(currentUser, workOrder);

			return View("edit");
		}

		public void Do(string command, string workOrderNumber, string assignee,
		               string title, string description)
		{
			WorkOrder workOrder = getWorkOrder(workOrderNumber);
			workOrder.Assignee = _employeeRepository.GetByUserName(assignee);
			workOrder.Title = title;
			workOrder.Description = description;

			IStateCommand[] commands =
				_workflowFacilitator.GetValidStateCommands(workOrder,
				                                           _userSession.GetCurrentUser());
			IStateCommand matchingCommand =
				Array.Find(commands,
				           delegate(IStateCommand obj) { return obj.Matches(command); });

			matchingCommand.Execute(_stateCommandVisitor);
		}

		public ActionResult Edit(string workOrderNumber)
		{
			WorkOrder workOrder = _workOrderRepository.GetWorkOrder(workOrderNumber);
			ViewData.Add(workOrder);

			pushEmployeeListToViewData(workOrder.Assignee);
			pushValidCommandsToViewData(_userSession.GetCurrentUser(), workOrder);

			return View();
		}

		private void pushEmployeeListToViewData(Employee selectedEmployee)
		{
			Employee[] allEmployees = _employeeRepository.GetAllEmployeesSorted();
			ViewData.Add(new EmployeeSelectList(allEmployees, selectedEmployee));
		}

		private void pushValidCommandsToViewData(Employee currentUser,
		                                         WorkOrder workOrder)
		{
			IStateCommand[] validCommands =
				_workflowFacilitator.GetValidStateCommands(workOrder, currentUser);
			ViewData.Add(validCommands);
		}

		private WorkOrder getWorkOrder(string workOrderNumber)
		{
			WorkOrder workOrder = _workOrderRepository.GetWorkOrder(workOrderNumber);
			if (workOrder != null)
			{
				return workOrder;
			}

			workOrder =
				_workOrderBuilder.CreateNewWorkOrder(_userSession.GetCurrentUser());
			workOrder.Number = workOrderNumber;
			return workOrder;
		}
	}
}